/*******************************************************************************
* FileName:         SPMatrix.cpp
* Author:           李智铭
* Student Number:   3022206093
* Date:             2024/11/6 17:00:00
* Version:          v1.0
* Description:      Data Structure Experiment #6
*
*******************************************************************************/

#include "SPMatrix.h"
#include <cstring>
#include <algorithm>
#include <iostream>
#include <stdexcept>

SPMatrix::SPMatrix(int r, int c, int max_element) : row(r), col(c), count(0), MAX_COUNT(max_element){       //带最大元素数构造
    a = new int*[row];
    for(int i = 0; i < row; i++) {     //逐行构造
        a[i] = new int[col]();
    }
}

SPMatrix::SPMatrix(int r, int c) : row(r), col(c), count(0), MAX_COUNT(r * c) {      //不带最大元素数构造
    a = new int*[row];
    for(int i = 0; i < row; i++) {      //逐行构造
        a[i] = new int[col]();
    }
}

int SPMatrix::get(int i, int j)const{
    if (i < 0 || i >= row || j < 0 || j >= col) {   //判断行号列号是否合法
        throw std::out_of_range("Index out of bounds");
    }
    return a[i][j];
}

void SPMatrix::set(int i, int j, int val) {
    if (i < 0 || i >= row || j < 0 || j >= col) {     //判断行号列号是否合法
        throw std::out_of_range("Index out of bounds");
    }
    if (count >= MAX_COUNT && val != 0) {    //判断当前元素个数是否超限 && 是否要置0
        std::cerr << "Exceeded max element limit." << std::endl;
        return;
    }

    if (a[i][j] == 0 && val != 0) count++;     // 原元素为0 && 置非0 -> 元素数量+1
    else if (a[i][j] != 0 && val == 0) count--;     // 原元素为非0 && 置0 -> 元素数量-1

    a[i][j] = val;
}

void SPMatrix::rotate() {
    SPMatrix result(col, row);
    for(int i = 0; i < row; i++) {
        for(int j = 0; j < col; j++) {
            result.a[j][i] = a[i][j];     // 对称赋值
        }
    }
    *this = result;     // result传递给this指针
}

SPMatrix SPMatrix::operator+(const SPMatrix& b){
    if (row != b.row || col != b.col) {     // 判断两矩阵是否同型
        throw std::invalid_argument("Matrix dimensions must match for addition");
    }

    SPMatrix res(row, col);
    for(int i = 0 ; i < row ; i++){
        for(int j = 0 ; j < col ; j++)
            res.a[i][j] = a[i][j] + b.a[i][j]; 
    }
    return res;
}

SPMatrix SPMatrix::operator-(const SPMatrix& b){
    if (row != b.row || col != b.col) {   // 判断两矩阵是否同型
        throw std::invalid_argument("Matrix dimensions must match for subtraction");
    }

    SPMatrix res(row, col);
    for(int i = 0 ; i < row ; i++){
        for(int j = 0 ; j < col ; j++)
            res.a[i][j] = a[i][j] - b.a[i][j]; 
    }
    return res;
}

SPMatrix SPMatrix::operator*(const SPMatrix& b){
    if (col != b.row) {     // 判断两矩阵是否能够进行乘法运算
        throw std::invalid_argument("Matrix dimensions must match for multiplication");
    }

    SPMatrix res(row, b.col);
    for(int i = 0 ; i < row ; i++){
        for(int j = 0 ; j < b.col ; j++){
            res.a[i][j] = 0;   //初始化为0
            for(int k = 0 ; k < col ; k++)
                res.a[i][j] += a[i][k] * b.a[k][j];
        }
    }
    return res;
}

SPMatrix::~SPMatrix(){
    for(int i = 0 ; i < row ; i++)   //逐行析构
        delete[] a[i];
    delete[] a;
}